package implementations;

import java.util.*;
import interfaces.Edge;
import interfaces.Vertex;
/**
 * 
 * @author Kai Bielenberg
 * @author Oliver Behnke
 *
 * @param <E>
 * @param <V>
 */
public abstract class AbstractEdge<E,V> extends AbstractGraphElement implements Edge<E,V> {

   protected Vertex<V> start, end;
   protected String name;
   protected E element = null;
    
    public Vertex<V> start() {
        return this.start;
    }
    

    public Vertex<V> end() {
        return this.end;
    }


    @Override
    public E element() {
       return this.element;
    }


    @Override
    public boolean areIncident(Vertex<V> v) {
        return this.start().equals(v) || this.end().equals(v);
    }


    @Override
    public Vertex<V> otherVertex(Vertex<V> v) {
        if (this.start().equals(v) ){
            return end();
        }
        return start();
    }


    @Override
    public boolean isLoop() {
        return this.start().equals(this.end());
    }


    @Override
    public boolean includes(Vertex<V> v) {
       return start().equals(v) || end().equals(v);
    }


    /**
     * @return List, first element is the start item, second element the end item.
     */
    @Override
    public Collection<Vertex<V>> vertices() {
        Set<Vertex<V>> result = new HashSet<Vertex<V>>();
        result.add(start);
        result.add(end);
        return result;
    }


    @Override
    public String name() {
        return this.name;
    }


    @Override
    public int hashCode() {
    // Record Access wieder in den gettern
    
    	double code = name.hashCode();
    	double code2 = element.hashCode();
    	double code3 = start.hashCode();
    	double code4 = end.hashCode();
    	long longBits = Double.doubleToLongBits(code + code2 + code3 + code4);
    	return (int) (longBits ^ (longBits >>> 32));
    	}


    public String toString() {
    		recordAccess();
    //		// Wenn "element" bei der Konstruktion nicht angegeben wurde, wird eine Standartbenennung ausgegeben
    //		// z.B. e(v1_v2);
    //		if (this.element() == null) {
    //			return ("e(" + v1.toString() + "_" + v2.toString() + ")");
    //		}
    //		return this.element.toString();
    		return this.name;
    	}
}
